#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Objective-C混淆器
专门处理Objective-C代码的混淆
"""

import os
import re
from typing import Dict, List, Set, Tuple
from ..builtin_config_module.builtin_config import BuiltInConfig
from ..utils_module.logger import ObfuscationLogger

class ObjCObfuscator:
    """Objective-C混淆器"""
    
    def __init__(self, config: BuiltInConfig, logger: ObfuscationLogger):
        self.config = config
        self.logger = logger
        
        # Objective-C语法模式
        self.patterns = {
            'interface': r'@interface\s+(\w+)',
            'implementation': r'@implementation\s+(\w+)',
            'protocol': r'@protocol\s+(\w+)',
            'method': r'[-+]\s*\([^)]*\)\s*(\w+)',
            'property': r'@property\s+\([^)]*\)\s*(\w+)',
            'variable': r'\b(\w+)\s*;',
            'typedef': r'typedef\s+.*\s+(\w+)'
        }
    
    def extract_symbols(self, file_path: str) -> List[str]:
        """提取Objective-C文件中的符号"""
        symbols = []
        
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            # 提取各种类型的符号
            for symbol_type, pattern in self.patterns.items():
                matches = re.findall(pattern, content)
                for match in matches:
                    if self.config.is_symbol_safe_to_obfuscate(match, 'objc', '')[0]:
                        symbols.append(match)
            
            # 去重
            symbols = list(set(symbols))
            
        except Exception as e:
            self.logger.log_error(f"提取Objective-C符号失败: {file_path}, 错误: {str(e)}")
        
        return symbols
    
    def obfuscate_file(self, file_path: str, symbol_map: Dict[str, str]):
        """混淆Objective-C文件"""
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            original_content = content
            
            # 保护字符串、注释和宏定义不被替换
            protected_regions = self._identify_protected_regions(content)
            
            # 按符号长度排序，优先替换长符号
            sorted_symbols = sorted(symbol_map.items(), key=lambda x: len(x[0]), reverse=True)
            
            for original, obfuscated in sorted_symbols:
                # 使用词边界确保精确替换
                pattern = r'\b' + re.escape(original) + r'\b'
                # 使用安全替换，避免修改保护区域
                content = self._safe_replace(content, pattern, obfuscated, protected_regions)
            
            # 检查是否有变化
            if content != original_content:
                if not self.config.dry_run:
                    with open(file_path, 'w', encoding='utf-8') as f:
                        f.write(content)
                
                self.logger.log_file_processing(file_path, "已混淆")
            else:
                self.logger.log_file_processing(file_path, "无需混淆")
                
        except Exception as e:
            self.logger.log_error(f"混淆Objective-C文件失败: {file_path}, 错误: {str(e)}")
    
    def extract_interface_symbols(self, content: str) -> List[str]:
        """提取接口符号"""
        interfaces = []
        pattern = r'@interface\s+(\w+)'
        matches = re.findall(pattern, content)
        for match in matches:
            if self.config.is_symbol_safe_to_obfuscate(match, 'objc', '')[0]:
                interfaces.append(match)
        return interfaces
    
    def extract_method_symbols(self, content: str) -> List[str]:
        """提取方法符号"""
        methods = []
        pattern = r'[-+]\s*\([^)]*\)\s*(\w+)'
        matches = re.findall(pattern, content)
        for match in matches:
            if self.config.is_symbol_safe_to_obfuscate(match, 'objc', '')[0]:
                methods.append(match)
        return methods
    
    def _identify_protected_regions(self, content: str) -> List[Tuple[int, int]]:
        """识别不应被混淆的区域（字符串、注释、宏等）"""
        regions = []
        
        # 多行注释 /* ... */
        for match in re.finditer(r'/\*.*?\*/', content, re.DOTALL):
            regions.append((match.start(), match.end()))
        
        # 单行注释 //
        for match in re.finditer(r'//.*?$', content, re.MULTILINE):
            regions.append((match.start(), match.end()))
        
        # 字符串 @"..." 和 "..."
        for match in re.finditer(r'@"(?:[^"\\]|\\.)*"|"(?:[^"\\]|\\.)*"', content):
            regions.append((match.start(), match.end()))
        
        # 预处理器指令 #...
        for match in re.finditer(r'^#.*?$', content, re.MULTILINE):
            regions.append((match.start(), match.end()))
            
        # import/include语句
        for match in re.finditer(r'#import\s+[<"].*?[>"]|#include\s+[<"].*?[>"]', content):
            regions.append((match.start(), match.end()))
            
        return sorted(regions)
    
    def _safe_replace(self, content: str, pattern: str, replacement: str, protected_regions: List[Tuple[int, int]]) -> str:
        """安全替换，跳过保护区域"""
        result = []
        last_pos = 0
        
        for match in re.finditer(pattern, content):
            # 检查是否在保护区域内
            in_protected = False
            for start, end in protected_regions:
                if start <= match.start() < end:
                    in_protected = True
                    break
            
            if not in_protected:
                # 添加匹配前的内容
                result.append(content[last_pos:match.start()])
                # 添加替换内容
                result.append(replacement)
                last_pos = match.end()
        
        # 添加剩余内容
        result.append(content[last_pos:])
        return ''.join(result)
    
    def extract_property_symbols(self, content: str) -> List[str]:
        """提取属性符号"""
        properties = []
        pattern = r'@property\s+\([^)]*\)\s*(\w+)'
        matches = re.findall(pattern, content)
        for match in matches:
            if self.config.is_symbol_safe_to_obfuscate(match, 'objc', '')[0]:
                properties.append(match)
        return properties
